From ac5f521c656d4f88e1b62c2e7e1d610850515ca9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Florian=20M=C3=BCllner?= Date: Tue, 10 Feb 2026 15:30:46 +0100 Subject: [PATCH] layout: Reject promise if background loading is interrupted Currently if a background manager is destroyed while we are waiting for the background to load, the corresponding promise never resolves. To prevent this from happening (and the startup animation getting stuck as a result), guard the loading operation with a cancellable and reject the promise when it is cancelled. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/9018 Part-of: --- js/ui/layout.js | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/js/ui/layout.js b/js/ui/layout.js index 8f07ac63e..362598d3c 100644 --- a/js/ui/layout.js +++ b/js/ui/layout.js @@ -525,16 +525,25 @@ export const LayoutManager = GObject.registerClass({ } } - _waitLoaded(bgManager) { - return new Promise(resolve => { - const id = bgManager.connect('loaded', () => { - bgManager.disconnect(id); - resolve(); - }); + _waitLoaded(bgManager, cancellable) { + const {promise, resolve, reject} = Promise.withResolvers(); + const cancelId = cancellable.connect(() => { + reject(new GLib.Error(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED, + 'Background loading was cancelled')); + }); + const loadedId = bgManager.connect('loaded', () => { + bgManager.disconnect(loadedId); + cancellable.disconnect(cancelId); + resolve(); }); + + return promise; } _updateBackgrounds() { + this._bgLoadCancellable?.cancel(); + this._bgLoadCancellable = null; + for (let i = 0; i < this._bgManagers.length; i++) this._bgManagers[i].destroy(); @@ -543,6 +552,9 @@ export const LayoutManager = GObject.registerClass({ if (Main.sessionMode.isGreeter) return Promise.resolve(); + const cancellable = new Gio.Cancellable(); + this._bgLoadCancellable = cancellable; + for (let i = 0; i < this.monitors.length; i++) { const bgManager = this._createBackgroundManager(i); this._bgManagers.push(bgManager); @@ -551,7 +563,8 @@ export const LayoutManager = GObject.registerClass({ bgManager.backgroundActor.hide(); } - return Promise.all(this._bgManagers.map(this._waitLoaded)); + return Promise.all( + this._bgManagers.map(mgr => this._waitLoaded(mgr, cancellable))); } _updateKeyboardBox() { -- 2.39.5